package com.psy.counseling.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.psy.counseling.entity.*;
import com.psy.counseling.mapper.AskMapper;
import com.psy.counseling.mapper.FirstVisitMapper;
import com.psy.counseling.mapper.SituationMapper;
import com.psy.counseling.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.psy.counseling.utils.Result;
import com.psy.counseling.utils.TimeUtil;
import com.psy.counseling.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author cxh
 * @since 2022-05-31
 */
@Service
@Slf4j
public class AskServiceImpl extends ServiceImpl<AskMapper, Ask> implements AskService {

    private final String SUBJECT = "来自心理社区的提醒邮件";
    private final String[] checkType = {"审核中", "审核未通过", "审核通过", "预约已取消"};
    @Autowired
    private AskMapper askMapper;
    @Autowired
    private FirstVisitService firstVisitService;
    @Autowired
    private FirstVisitMapper firstVisitMapper;
    @Autowired
    private UserService userService;
    @Autowired
    private SituationMapper situationMapper;
    @Autowired
    private MailService mailService;
    @Autowired
    private ScheduleServiceImpl scheduleService;

    @Transactional
    @Override
    public Page listAsks(Ask ask, PageVO page) {
        Page<Ask> askPage = new Page<>(page.getPageNum(), page.getPageSize());
        LambdaQueryWrapper<Ask> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StringUtils.isNotBlank(ask.getCheckState()), Ask::getCheckState, ask.getCheckState())
                .eq(ask.getTeacherId() != null, Ask::getTeacherId, ask.getTeacherId())
                .ge(StringUtils.isNotBlank(ask.getStartTime()), Ask::getStartTime, ask.getStartTime())
                .le(StringUtils.isNotBlank(ask.getEndTime()), Ask::getEndTime, ask.getEndTime());
        askPage = this.page(askPage, queryWrapper);
        return askPage;
    }

    @Transactional
    @Override
    public List<Ask> getAskRecord(Long id) {
        List<Ask> askRecord = askMapper.getAskRecord(id);
        return askRecord;
    }

    @Transactional
    @Override
    public Result deleteAskRecord(DeleteVO deleteVO, Integer flag) {
        if (flag == 0 && deleteVO.getId() != null) {
            this.removeById(deleteVO.getId());
            return Result.success();
        }
        if (flag != 0 && deleteVO.getIds() != null) {
            this.removeByIds(deleteVO.getIds());
            return Result.success();
        }
        return Result.error("204", "删除失败");
    }

    @Transactional
    @Override
    public Result addAsk(Ask ask, Long userId) {
        if (ask != null && userId != null) {
            LambdaQueryWrapper<FirstVisit> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(FirstVisit::getStudentId, userId).orderByDesc(FirstVisit::getEndTime);
            List<FirstVisit> visits = firstVisitService.list(wrapper);
            log.info("{}", visits);
            if (visits != null && visits.size() > 0) {
                FirstVisit visit = visits.get(0);
                LambdaQueryWrapper<Ask> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(Ask::getVisitId, visit.getId());
                if (this.count(queryWrapper) == 0) {
                    User user = userService.getById(userId);
                    ask.setEndTime(TimeUtil.timeOperation(ask.getEndTime(), 7L * 24 * 60 * ask.getTotal()));
                    ask.setVisitId(visit.getId());
                    ask.setSno(user.getUsername());
                    ask.setSex(user.getSex());
                    ask.setFaculty(user.getFaculty());
                    ask.setTelephone(user.getTelephone());
                    ask.setRealName(user.getRealName());
                    ask.setPlace("心理咨询室");
                    ask.setCheckState("审核中");
                    ask.setDay(TimeUtil.getDayWeekOfDate(ask.getStartTime()));
                    this.save(ask);
                    return Result.success();
                }
            }
        }
        return Result.error("204", "申请失败");
    }

    @Transactional
    @Override
    public Result<?> addAskTime(AskVO askVO) {
        if (askVO != null && askVO.getId() != null && askVO.getAddNum() != null && askVO.getAddNum() > 0) {
            Ask ask = this.getById(askVO.getId());
            LambdaUpdateWrapper<Ask> wrapper = new LambdaUpdateWrapper<>();
            String endTime = TimeUtil.timeOperation(ask.getEndTime(), 7L * 24 * 60 * askVO.getAddNum());
            wrapper.eq(Ask::getId, ask.getId())
                    .set(Ask::getTotal, ask.getTotal() + askVO.getAddNum())
                    .set(Ask::getEndTime, endTime);
            this.update(wrapper);
            return Result.success();
        }
        return Result.error("204", "追加失败");
    }

    @Override
    public Result suspendAsk(AskVO askVO) {
        if (askVO != null && askVO.getId() != null) {
            LambdaQueryWrapper<Situation> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Situation::getAskId, askVO.getId());
            Integer count = situationMapper.selectCount(queryWrapper);
            Ask ask = this.getById(askVO.getId());
            String endTime = TimeUtil.timeOperation(ask.getEndTime(), 7L * 24 * 60 * (ask.getTotal() - count), false);

            log.info(endTime + "   " + ask.getTotal() + "   " + count);

            LambdaUpdateWrapper<Ask> wrapper = new LambdaUpdateWrapper<>();
            wrapper.eq(Ask::getId, askVO.getId()).set(Ask::getTotal, count).set(Ask::getEndTime, endTime);
            this.update(wrapper);
            return Result.success();
        }
        return Result.error("204", "中止失败");
    }

    @Transactional
    @Override
    public Result<?> rejectAsk(Long id) {
        if (id != null) {
            LambdaUpdateWrapper<Ask> wrapper = new LambdaUpdateWrapper<>();
            wrapper.eq(Ask::getId, id).set(Ask::getCheckState, checkType[1]);
            this.update(wrapper);
            sendMsg(id, false);
            return Result.success();
        }
        return Result.error("204", "驳回失败");
    }

    @Transactional
    @Override
    public Result<?> viaAsk(Ask ask) {
        // 用于记录该咨询时间段，咨询师是否值班
        Boolean flag = false;
        if (ask != null && ask.getTeacherId() != null && ask.getStartTime() != null && ask.getEndTime() != null) {
            Integer dayWeek = TimeUtil.getDayWeekOfDate(ask.getStartTime());
            //获取某个咨询师周几的值班安排
            LambdaQueryWrapper<Schedule> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Schedule::getDay, dayWeek)
                    .eq(Schedule::getUseId, ask.getTeacherId())
                    .orderByDesc(Schedule::getStart);
            List<Schedule> schedules = scheduleService.list(wrapper);
            String aSTime = TimeUtil.getTime(ask.getStartTime());
            String aETime = TimeUtil.getTime(ask.getEndTime());
            String sTime = null;
            String eTime = null;
            for (Schedule s : schedules) {
                if (aSTime.compareTo(s.getStart()) >= 0 && aETime.compareTo(s.getEnd()) <= 0) {
                    sTime = s.getStart();
                    eTime = s.getEnd();
                    flag = true;
                    break;
                }
            }
            //如果咨询师该时间段值班
            if (flag) {
                // 查询该咨询师在该时间段是否有初访
                LambdaQueryWrapper<FirstVisit> firstVisitLambdaQueryWrapper = new LambdaQueryWrapper<>();
                firstVisitLambdaQueryWrapper.eq(FirstVisit::getVisitorId, ask.getTeacherId())
                        //审核通过
                        .eq(FirstVisit::getCheckState, checkType[2])
                        .ge(FirstVisit::getStartTime, TimeUtil.formatHhMmSsOfDate(ask.getStartTime(), true))
                        .lt(FirstVisit::getEndTime, TimeUtil.formatHhMmSsOfDate(ask.getStartTime(), false))
                        .orderByDesc(FirstVisit::getStartTime);

                List<FirstVisit> firstVisits = firstVisitService.list(firstVisitLambdaQueryWrapper);
                String askStartTime = ask.getStartTime();
                String askEndTime = TimeUtil.timeOperation(ask.getEndTime(), 7L * 24 * 60 * ask.getTotal(), false);
                for (FirstVisit f : firstVisits) {
                    if ((askStartTime.compareTo(f.getStartTime()) <= 0 && askEndTime.compareTo(f.getEndTime()) >= 0)
                            || (askStartTime.compareTo(f.getStartTime()) >= 0 && askStartTime.compareTo(f.getEndTime()) < 0)
                            || (ask.getEndTime().compareTo(f.getStartTime()) > 0 && ask.getEndTime().compareTo(f.getEndTime()) <= 0)) {
                        sendMsg(ask.getId(), false);
                        return Result.error("204", "审核未通过");
                    }
                }

                LambdaQueryWrapper<Ask> askLambdaQueryWrapper = new LambdaQueryWrapper<>();
                askLambdaQueryWrapper.eq(Ask::getDay, ask.getDay())
                        .eq(Ask::getTeacherId, ask.getTeacherId())
                        .eq(Ask::getCheckState, checkType[2])
                        .ge(Ask::getEndTime, ask.getStartTime())
                        .le(Ask::getEndTime, ask.getEndTime())
                        .orderByAsc(Ask::getEndTime);
                List<Ask> asks = this.list(askLambdaQueryWrapper);
                for (Ask a : asks) {
                    if (!((TimeUtil.getTime(ask.getStartTime()).compareTo(TimeUtil.getTime(a.getEndTime())) >= 0)
                            || (TimeUtil.getTime(ask.getEndTime()).compareTo(TimeUtil.getTime(a.getStartTime())) <= 0))) {
                        sendMsg(ask.getId(), false);
                        return Result.error("204", "审核未通过");
                    }
                }
                ask.setCheckState(checkType[2]);
                this.updateById(ask);
                sendMsg(ask.getId(), true);
                return Result.success("审核通过");
            } else {
                sendMsg(ask.getId(), false);
                return Result.error("204", "审核未通过");
            }
        }
        return Result.error("204", "审核未通过,缺失参数");
    }

    /**
     * 通过咨询id向学生邮箱发送咨询预约详情
     *
     * @param id
     * @param isVia
     */
    public void sendMsg(Long id, boolean isVia) {
        SendInfoVO sendInfo = askMapper.getSendInfo(id);
        if (sendInfo.getEmail() != null) {
            //发送邮箱
            String content = null;
            if (isVia) {
                content = "亲爱的" + sendInfo.getRealName() + ",您好：" + "您预约的" + sendInfo.getTeacherName() + "老师的" + sendInfo.getStartTime() + "~" + TimeUtil.timeOperation(sendInfo.getEndTime(), 7L * 24 * 60 * sendInfo.getTotal(), false) + "的心理咨询预约成功，疗程为" + sendInfo.getTotal() + "周";
            } else {
                content = "亲爱的" + sendInfo.getRealName() + ",您好：" + "您预约的" + sendInfo.getTeacherName() + "老师的" + sendInfo.getStartTime() + "~" + TimeUtil.timeOperation(sendInfo.getEndTime(), 7L * 24 * 60 * sendInfo.getTotal(), false) + "的心理咨询时间段，已被预约，如有需要请重新申请心理咨询预约！！！";
            }
            mailService.sendMimeMail(sendInfo.getEmail(), SUBJECT, content);
        }
    }


    @Transactional
    @Override
    public Result<?> cancelAsk(Long id) {
        if (id != null) {
            Date now = new Date();
            Ask ask = this.getById(id);
            String startTime = TimeUtil.timeOperation(ask.getStartTime(), 24L * 60, false);
            Date start = TimeUtil.strToDateTime(startTime);
            if (now.before(start)) {
                ask.setCheckState(checkType[3]);
                this.save(ask);
                return Result.success("预约取消成功");
            }
        }
        return Result.error("204", "预约取消失败");
    }

    @Transactional
    @Override
    public Result<?> getStatus(Long id) {
        if (id == null) {
            return Result.error("204", "为获取到对应参数");
        }
        Date now = new Date();
        Ask ask = this.getById(id);
        Date startTime = TimeUtil.strToDateTime(ask.getStartTime());
        Date endTime = TimeUtil.strToDateTime(ask.getEndTime());
        if (now.before(startTime)) {
            return Result.success("咨询未开始");
        }
        if (now.before(endTime) && now.after(startTime)) {
            return Result.success("咨询进行中");
        }
        return Result.success("咨询已结束");
    }

    @Transactional
    @Override
    public List<AnalysisVO> getAskTeacherInfo(String teacherName) {
        List<AnalysisVO> analysisVOList = askMapper.listAskRecord(StringUtils.toStringTrim(teacherName));
        // 获取安照条件查询出来的咨询师id
        List<Long> ids = analysisVOList.stream().map(AnalysisVO::getTeacherId).collect(Collectors.toList());
        //将满足条件的老师咨询信息找出来
        LambdaQueryWrapper<Ask> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Ask::getCheckState, checkType[2]).in(Ask::getTeacherId, ids).orderByAsc(Ask::getTeacherId);
        List<Ask> asks = askMapper.selectList(queryWrapper);
        //将满足条件的初访信息找出来
        LambdaQueryWrapper<FirstVisit> firstVisitLambdaQueryWrapper = new LambdaQueryWrapper<>();
        firstVisitLambdaQueryWrapper.eq(FirstVisit::getCheckState, "审核通过")
                .in(FirstVisit::getVisitorId, ids)
                .orderByAsc(FirstVisit::getId);
        List<FirstVisit> firstVisits = firstVisitMapper.selectList(firstVisitLambdaQueryWrapper);
        //获取对应老师的总咨询时间
        Map<Long, Integer> map = new HashMap<>();
        // 获取对应老师的总咨询次数
        Map<Long, Integer> mapCount = new HashMap<>();
        for (Ask ask : asks) {
            //获取已经咨询的次数
            LambdaQueryWrapper<Situation> situationLambdaQueryWrapper = new LambdaQueryWrapper<>();
            situationLambdaQueryWrapper.eq(Situation::getAskId, ask.getId());
            Integer curNum = situationMapper.selectCount(situationLambdaQueryWrapper);

            Date endDate = TimeUtil.strToDateTime(TimeUtil.timeOperation(ask.getEndTime(), 7L * 24 * 60 * ask.getTotal(), false));
            Date startDate = TimeUtil.strToDateTime(ask.getStartTime());
            map.put(ask.getTeacherId(), map.getOrDefault(ask.getTeacherId(), 0) + TimeUtil.getHours(endDate.getTime() - startDate.getTime()) * curNum);
            mapCount.put(ask.getTeacherId(), mapCount.getOrDefault(ask.getTeacherId(), 0) + curNum);
        }
        for (FirstVisit f : firstVisits) {
            Long time = TimeUtil.strToDateTime(f.getEndTime()).getTime() - TimeUtil.strToDateTime(f.getStartTime()).getTime();
            map.put(f.getVisitorId(), map.getOrDefault(f.getVisitorId(), 0) + TimeUtil.getHours(time));
            mapCount.put(f.getVisitorId(), mapCount.getOrDefault(f.getVisitorId(), 0) + 1);
        }
        for (AnalysisVO a : analysisVOList) {
            a.setHours(map.get(a.getTeacherId()));
            a.setCount(mapCount.get(a.getTeacherId()));
        }
        return analysisVOList;
    }

    @Override
    public Page<Ask> getAskInfo(String userName, String teacherName, Page<Ask> page) {
        askMapper.getAskInfo(userName,teacherName,page);
        return null;
    }


}
